<?php

namespace app\admin\service;

use app\api\service\CommonService;
use app\event\AgentAddSuccess;
use app\model\Agent as ModelAgent;
use app\model\AgentSalesman;
use fast\Random;
use think\facade\Db;

class Agent extends CommonService
{
    /*
     代理商保存
     $param [base=>'主表基础信息','service_config'=>[各种业务配置,'suppliers'=>[供应商列表]]];
     主要包括基础信息，供应商信息 配置信息（以serv_type为key 的数组）
     1，配置信息校验是否合理
     2，存在性校验
     3，服务配置中提取 供应商配置信息
     4，入库主逻辑 入库基础信息=> 删除表里代理供应商，入库代理供应商 => 入库服务配置表

    */
    public function save($param, $id = 0)
    {
        // service config 校验
        $agentServiceConfig = new AgentServiceConfig();
        $res = $agentServiceConfig->validate($param['service_config']);
        if ($res['code']) {
            return $this->inValiReturn($res['msg']);
        }

        // 配置里面剥离话费充值部分，该部分延用原有结构
        if (isset($param['service_config'][PRODUCT_MOBILE_SERV])) {
            $param['base']['mobile_discount_fast'] = $param['service_config'][PRODUCT_MOBILE_SERV]['discount_fast'] ?? 99.99;
            $param['base']['mobile_discount_slow'] = $param['service_config'][PRODUCT_MOBILE_SERV]['discount_slow'] ?? 99.99;
        }

        // 存在性校验
        $existsUsername = ModelAgent::where('id', '<>', $id)
            ->where('username', '=', $param['base']['username'])
            ->field('id')->find();
        if ($existsUsername) {
            return $this->inValiReturn('账号已经存在，id=' . $existsUsername['id']);
        }
        $existsMobile = ModelAgent::where('id', '<>', $id)
            ->where('mobile', '=', $param['base']['mobile'])
            ->field('id')->find();
        if ($existsMobile) {
            return $this->inValiReturn('手机号已经存在，id=' . $existsMobile['id']);
        }

        // step 提取 业务供应商配置信息
        $suppliersArr = [];
        foreach ($param['service_config'] as $k => $v) {
            if (empty($v['supplier_id'])) {
                continue;
            }

            if (PRODUCT_MOBILE_SERV == $k) {
                foreach ($v['supplier_id'] as $k2 => $v2) {
                    $suppliersArr[$k][] = ['mobile_supplier_id' => $v2];
                }
                continue;
            }

            $supplierIds = Db::name('base_supplier')
                ->whereIn('id', $v['supplier_id'])
                ->where('serv_type', $k)
                ->column('id');
            foreach ($supplierIds as $k2 => $v2) {
                $suppliersArr['other'][] = ['supplier_id' => $v2, 'serv_type' => $k];
            }

            unset($param['service_config'][$k]['supplier_id']);
        }

        // 代理商分配的 业务员
        $salesmanArr = [];
        foreach ($param['service_config'] as $ks => $vs) {
            if (empty($vs['salesman_id'])) {
                continue;
            }
            $salesmanArr[] = ['salesman_id' => $vs['salesman_id'], 'serv_type' => $vs['serv_type']];
            unset($param['service_config'][$ks]['salesman_id']);
        }

        if ($id) {
            $model = ModelAgent::find($id);
        } else {
            $model = new ModelAgent();
        }

        if (empty($model->app_key)) {
            $appKey = $this->getKey('app_key', 16);
            if (false === $appKey) {
                return $this->inValiReturn('app_key 生成失败，请重试');
            }
            $model->app_key = $appKey;
        }
        if (empty($model->app_secret)) {
            $appSecret = $this->getKey('app_secret', 32);
            if (false === $appSecret) {
                return $this->inValiReturn('app_secret 生成失败，请重试');
            }
            $model->app_secret = $appSecret;
        }

        // step 开始处理入库
        Db::startTrans();
        try {
            if ($param['base']) {
                foreach ($param['base'] as $k => $v) {
                    $model->{$k} = $v;
                }
                if (!$model->save()) {
                    Db::rollback();

                    return $this->inValiReturn('保存失败，' . __LINE__);
                }
            }

            if (!$model->id) {
                // Db::rollback();

                return $this->inValiReturn('保存失败，' . __LINE__);
            }
            // 话费业务供应商相关
            //$model->together(['supplier'])->delete(); // 先清空后入库
            Db::name('agent_mobile_supplier')->where('agent_id', $model->id)->delete();
            if (!empty($suppliersArr[PRODUCT_MOBILE_SERV])) {
                $res = $model->mobileSupplier()->saveAll($suppliersArr[PRODUCT_MOBILE_SERV]);
                if (!$res) {
                    Db::rollback();

                    return $this->inValiReturn('保存失败，' . __LINE__);
                }
                unset($suppliersArr[PRODUCT_MOBILE_SERV]);
            }

            // 其他业务务供应商相关
            $model->supplier()->where('agent_id', $model->id)->delete();
            if (!empty($suppliersArr['other'])) {
                $suppliersArr = $suppliersArr['other'];
                $res = $model->supplier()->saveAll($suppliersArr);
                if (!$res) {
                    Db::rollback();

                    return $this->inValiReturn('保存失败，' . __LINE__);
                }
            }

            // 代理商关联业务员
            $salesmanStatus =$this->saveSalesman($model, $salesmanArr);
            if (!$salesmanStatus) {
                Db::rollBack();
                return $this->inValiReturn('保存失败，' . __LINE__);
            }

            // 处理 业务配置
            if ($param['service_config']) {
                $serviceConfigs = $model->serviceConfig()->select();
                if (!$serviceConfigs->isEmpty()) {
                    // 对数据库存在的数据进行更新
                    foreach ($serviceConfigs as $k => $v) {
                        if (!isset($param['service_config'][$v->serv_type])) { // 数据库存在的数 没提交的数据不处理
                            continue;
                        }
                        foreach ($param['service_config'][$v->serv_type] as $k2 => $v2) {
                            $v->{$k2} = $v2;
                        }
                        if (!$v->save()) {
                            Db::rollback();

                            return $this->inValiReturn('保存失败，' . __LINE__);
                        }
                        unset($param['service_config'][$v->serv_type]);
                    }
                    // 不存在的数据库的直接入库
                    $configs = array_values(array_filter($param['service_config']));
                    if ($configs) {
                        $res = $model->serviceConfig()->saveAll($configs);
                        if (!$res) {
                            Db::rollback();

                            return $this->inValiReturn('保存失败，' . __LINE__);
                        }
                    }
                } else {
                    $res = $model->serviceConfig()->saveAll(array_values(array_filter($param['service_config'])));
                    if (!$res) {
                        Db::rollback();

                        return $this->inValiReturn('保存失败，' . __LINE__);
                    }
                }
            }

            //新增代理-----成功初始化----触发事件
            //add by ymzhang 2022-08-31 16:30
            if ($id == 0) {
                event(new AgentAddSuccess($model));
            }
            Db::commit();

            return $this->valiReturn();
        } catch (\Exception $e) {
            $msg = getExceptionMsg($e);
            doLog($msg);
            Db::rollback();
            if (isProd()) {
                $msg = '操作失败，请重试或者联系我们';
            }

            return $this->inValiReturn($msg);
        }

        return $this->inValiReturn('操作失败' . __LINE__);
    }

    /**
     * 生成 app_key, app_secret.
     */
    private function getKey($field, $len)
    {
        for ($i = 0; $i < 21; ++$i) {
            $str = Random::alnumlow($len);
            $id = Db::name('agent')
                ->where($field, $str)
                ->value('id');
            if (empty($id)) {
                return $str;
            }
        }

        return false;
    }

    /**
     * 代理商关联业务员
     * @param $model
     * @param $salesmanArr
     * @return array|bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected function saveSalesman($model, $salesmanArr) {
        // 代理商关联业务员
        // 代理商的业务员 检查下是新增还是修改  1、代理商新增时，业务员直接追加即可  2、修改时，业务员特殊处理，不能直接删除
        $bRet = true;
        if ($salesmanArr) {
            foreach ($salesmanArr as $item) {
                // 查看下 该代理商 分配的产品 是否关联业务员
                $salesmanId = $item['salesman_id'];
                $agentId = $model->id;
                $agentSalesmanModel = AgentSalesman::where([
                    'agent_id' => $agentId,
                    'serv_type' => $item['serv_type'],
                    'is_deleted' => DELETE_TYPE_NO,
                ])->find();

                $bAddSalesman = true;  // 是否新增业务员

                if ($agentSalesmanModel) {
                    if ($agentSalesmanModel->salesman_id == $salesmanId) {
                        $bAddSalesman = false;
                    } else {
                        // 旧的业务员先删除 在保存新的业务员
                        $agentSalesmanModel->is_deleted = DELETE_TYPE_YES;
                        if ($agentSalesmanModel->save() === false) {
                            return false;
                        }
                        $bAddSalesman = true;
                    }
                }

                if ($bAddSalesman) {
                    // 新增业务员
                    $agentSalesmanModelNew = new AgentSalesman();
                    $item['agent_id'] = $agentId;
                    if ($agentSalesmanModelNew->save($item) === false) {
                        return false;
                    }
                }
            }

        } else {
            // 所以的业务员取消 把原先配置好的 虚拟删除
            $agentSalesmanModel = AgentSalesman::where('agent_id', $model->id)->field('id')->select();
            if ($agentSalesmanModel) {
                $agentSalesmanArr = $agentSalesmanModel->toArray();
                array_walk($agentSalesmanArr, function (&$v, $k) {
                    $v['is_deleted'] = DELETE_TYPE_YES;
                });

                $agentSalesmanModelNew = new AgentSalesman();
                if (!$agentSalesmanModelNew->saveAll($agentSalesmanArr)) {
                    return false;
                }
            }
        }

        return $bRet;
    }
}
